package com.inner;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Hex;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * 参考《银联商务内部接口规范V0.7》
 * @author wuwenzhe
 *
 */
public class App {
	private static final String pubKey="30819f300d06092a864886f70d010101050003818d00308189028181008175f4290466f25d0a95984ddc173bf671913b52ea1c7093631aecdb9cdd378426806d3f98b3c72fd8468f217c16b0b9629ec41ee766ab05ee6661425271d97df85c81e026e7f4b2f784917c0f2223829392d59ecae232682aa98fd34f4c34d44c7b7cea132d3da838f72e798c5fc94ab9d442948677695e8b5c129e35e323ad0203010001";
	private static final String priKey="30820276020100300d06092a864886f70d0101010500048202603082025c020100028181008175f4290466f25d0a95984ddc173bf671913b52ea1c7093631aecdb9cdd378426806d3f98b3c72fd8468f217c16b0b9629ec41ee766ab05ee6661425271d97df85c81e026e7f4b2f784917c0f2223829392d59ecae232682aa98fd34f4c34d44c7b7cea132d3da838f72e798c5fc94ab9d442948677695e8b5c129e35e323ad020301000102818050e0cee39d236f809eef2c52601087de83beb6b02b200f5894ceaa70dd03fafded4bc874b5c282cb2a339291d9c3172f0a24a3e3a6af26633337f4c5095aa503c102b67baf61b886721867e9246348a689e93e70f7490fac360daab8dc8e23a87a9d3881957ca31a83b5ccf1638af6992693a5e84e84535f405a770d0caa03c5024100c0b4c8011cf5455a083f04888d1dbb4bea5e9e5f717855ad4e70b950937d461362831cd54a01f5faabe4bf57e580dc873e8c89badfa587fe44aab29685c4cacb024100abfb56c3df471a10ce9d84b0272edfdd4201994e3b6ea21a986ea162a4c148296ca38a132901e8bcd2314629cbc247e4fb5c0d6f82dd0c571e28b8dd1a732467024055df3950e5aa9660ec53c89d60e4e2d58d76e473fb8878056672ece16f17dfe63b7bd999620545ab9275b89e5e72f1d28298f5b7047a2b03af6db16f49e4cbc9024060558b46707d3d6688b5c72b7ce74ed27b34b611124d6854096a7ecfe885b3cc306472e544a5231f1186344d192b9c65f13ea0f003979a5ffa2ec94e60907aa5024100b00681e2c60e1aad79c691aadec72a47bcd89b677a8df7c10eff4445647e7d4890ea73a11451fe97d9f3d9dd3626ea3b31fd5593757b3f1f9fd478775097be47";
//	private static final String priKey="30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100943b9c6232e038dd937047a8e53d6112c4bc714d42d6904bb29e654f74bd73b04af881caa1d5b363a4bf5105717e400d47ffe728e8daba6a9b0df0a14117d708cbb1cf89e060b9ec653990b6eb8a34228f451031cf60a479f971c3fe2072a1a2b75be09156a71e58998248d82c144d48c26af8b8827f271a7bc730e0ed2775a3020301000102818100837c8112661898b88b311c8f8790b38be771547b791f446db12a69a95a5f36c0992fe8496ad659c2b87f700a090b391bced3032439b0d38cfeaf15d4a41dd68239bd96e1f3274ed335c76122f021a9475bd6ada31591d51fdd494f397df06ff0a272518262dcc66099234d510f6948bd46b6547ee691a3b90667e7a74ad80389024100ec6bb0df4ebc84c39fac448ca11bb0842dcde0a7a3db4b3c3166991170befd3eeeb2125ad6f52c52de9293861850071c11c15f1f7fca550edb7ba09c458feead024100a0824461adc5671ded58753cb02e4b121bfbe151646ac06ab5e40d431bae3e665f1b6083848e5a8add678ea7925df41f596c31a6e0a5517580ed8ebf7f790f8f024028d6111f01429ecc0b707e06ac6d53f800d166d48e00fae5d2c29dfddd33a01a96b03b6b6565c3da2c87b4e39c9f761aeb163390054ab5967362cf432ee0c5a102410089a74e97eadcaa13bb72aa90d293d12405c5ddb5dd05c4617ffec5f4f0af5daa9414399071455897514c37c6b4bb48dafde8d12849eeddce8534b6c0bac50b37024100aedbb826069f0ae5ee71851446b2d327b9616a4f2f837198d6a420c29aa474707f9e5870c96cbb9135c798d5b377f799c3aa73a920b608af7fdfbe4802e11f65";
//	private static final String pubKey="30819f300d06092a864886f70d010101050003818d0030818902818100943b9c6232e038dd937047a8e53d6112c4bc714d42d6904bb29e654f74bd73b04af881caa1d5b363a4bf5105717e400d47ffe728e8daba6a9b0df0a14117d708cbb1cf89e060b9ec653990b6eb8a34228f451031cf60a479f971c3fe2072a1a2b75be09156a71e58998248d82c144d48c26af8b8827f271a7bc730e0ed2775a30203010001";
	
	private static String HEAD_SEPARATOR = "\"";
	private static String TAIL_SEPARATOR = ",\"MsgMac\":";
	
	public static void main(String[] args) throws Exception{
		String msg=getRequestMsg();
		System.out.println(msg);
		boolean result=verify(msg);
		System.out.println("验签结果:"+result);
	}
	
    public static String getRequestMsg() throws Exception{
		OutputMessageProto requestMsg=new OutputMessageProto();
		MsgHeadProto head=new MsgHeadProto();

		requestMsg.setMsgHead(head);
		
		Map<String,String> body=new HashMap<String,String>();
		requestMsg.setMsgBody(body);
		
		body.put("userNo", "370203");
		body.put("acctNo", "4349100110489705");
		body.put("acctName", "姜志军");
		body.put("certNo", "339005198203045421");
		body.put("certType", "00");
		body.put("phone", "18321058884");
		
		head.setCharSet(MsgHeadProto.CHARSET_UTF8);
		head.setEncryptCertId("123456789");
		head.setMsgNum(MsgHeadProto.MSG_TOTAL_NUM);
		head.setMsgTotalNum(MsgHeadProto.MSG_TOTAL_NUM);

		head.setOrgReceiverID("0000000004");
		head.setOrgSendDate("20161012");
		//对应channelID标志调用者身份
		head.setOrgSenderID("10009");
		head.setOrgSendTime("110454");
		head.setOrgSendTransID("010101010101");
		//serviceID，标志所请求的服务
		head.setTransID("00005");
		head.setTransName("实名验证");
		head.setTransParentFlag(MsgHeadProto.TRANSPARENT_FLAG_DONOT_GET_THROUGH);
		head.setTransParentType(MsgHeadProto.TRANSPARENT_TYPE_NONE);
		head.setTransType(MsgHeadProto.TRANS_TYPE_INFO);
		head.setVersionID(MsgHeadProto.VERSION_ID);
		head.setType(MsgHeadProto.TYPE_REQUEST);
		
		String messageStr = JSON.toJSONString(requestMsg);
		byte[] messageBytes = messageStr.getBytes("UTF-8");
		
		byte[] priKeyBytes=null;
		try {
			priKeyBytes = Hex.decodeHex(priKey.toCharArray());
		} catch (Exception e) {
			throw new RuntimeException("私钥格式错误，bad format privateKey",e);
		}
		byte[] signature = SignatureUtils.sign(messageBytes, priKeyBytes);

		// 产生MsgMac部分
		String signatureStr=Hex.encodeHexString(signature);
		MsgMacProto mac=new MsgMacProto();
		requestMsg.setMsgMac(mac);
		mac.setSignature(signatureStr);
		// 返回打包结果
		String requestStr = JSON.toJSONString(requestMsg);
		return requestStr;
    }
    
    /**
     * 验证签名
     * @return
     * @throws Exception 
     */
    public static boolean verify(String requestStr) throws Exception{
    	OutputMessageProto msg=JSONObject.parseObject(requestStr, OutputMessageProto.class);
    	String sign=msg.getMsgMac().getSignature();
    	byte[] sigBytes = Hex.decodeHex(sign.toCharArray());
    	
		int beginIndex = requestStr.indexOf(HEAD_SEPARATOR);
		int endIndex = requestStr.lastIndexOf(TAIL_SEPARATOR);
		String message = requestStr.substring(beginIndex, endIndex);
		String messageWithBracket="{"+message+"}";
		byte[] messageBytes = messageWithBracket.getBytes("UTF-8");
		
		byte[] pubKeyBytes=Hex.decodeHex(pubKey.toCharArray());
		
		boolean verifyResult = SignatureUtils.verify(messageBytes,
				pubKeyBytes, sigBytes);
		return verifyResult;
    }
    
}
